summaryrefslogtreecommitdiff
path: root/app/api/auth/[...nextauth]/route.ts
blob: 609a63d71816036b6b463f2cd6c9bb13be672308 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// (1) next-auth에서 필요한 타입들을 import
import NextAuth, {
  NextAuthOptions,         // authOptions에 쓸 타입
  Session,
  User
} from 'next-auth'
import { JWT } from "next-auth/jwt"

import CredentialsProvider from 'next-auth/providers/credentials'

import { verifyOtp } from '@/lib/users/verifyOtp'

// 1) 모듈 보강 선언
declare module "next-auth" {
  /**
   * Session 객체를 확장
   */
  interface Session {
    user: {
      /** 우리가 필요로 하는 user id */
      id: string

      // 기본적으로 NextAuth가 제공하는 name/email/image 필드
      name?: string | null
      email?: string | null
      image?: string | null
      companyId?: number | null
      domain?: string | null

    }
  }

  /**
   * User 객체를 확장
   */
  interface User {
    id: string
    imageUrl?: string | null
    companyId?: number | null
    domain?: string | null
    // 필요한 필드를 추가로 선언 가능
  }
}

// (2) authOptions에 NextAuthOptions 타입 지정
export const authOptions: NextAuthOptions = {
  providers: [
    CredentialsProvider({
      name: 'Credentials',
      credentials: {
        email: { label: 'Email', type: 'text' },
        code: { label: 'OTP code', type: 'text' },
      },
      async authorize(credentials, req) {
        const { email, code } = credentials ?? {}

        // OTP 검증
        const user = await verifyOtp(email ?? '', code ?? '')
        if (!user) {
          return null
        }

        return {
          id: String(user.id ?? email ?? "dts"), 
          email: user.email,
          imageUrl: user.imageUrl ?? null,
          name: user.name,   // DB에서 가져온 실제 이름
          companyId: user.companyId,   // DB에서 가져온 실제 이름
          domain: user.domain,   // DB에서 가져온 실제 이름
        }
      },
    })
  ],
  // (3) session.strategy는 'jwt'가 되도록 선언
  //     필요하다면 as SessionStrategy 라고 명시해줄 수도 있음
  //     예) strategy: 'jwt' as SessionStrategy
  session: {
    strategy: 'jwt',
  },
  callbacks: {
    // (4) 콜백에서 token, user, session 등의 타입을 좀 더 명시해주고 싶다면 아래처럼 destructuring에 제네릭/타입 지정
    async jwt({ token, user }: { token: JWT; user?: User }) {
      if (user) {
        token.id = user.id
        token.email = user.email
        token.name = user.name
        token.companyId = user.companyId
        token.domain = user.domain
          ; (token as any).imageUrl = (user as any).imageUrl
      }
      return token
    },
    async session({ session, token }: { session: Session; token: JWT }) {
      if (token) {
        session.user = {
          id: token.id as string,
          email: token.email as string,
          name: token.name as string,
          domain: token.domain as string,
          companyId: token.companyId as number,
          image: (token as any).imageUrl ?? null
        }
      }
      return session
    },
  },
}

const handler = NextAuth(authOptions)

export { handler as GET, handler as POST }